/*
*/

#include "form.h"

#define	PERIOD_36	2000
#define	PERIOD_38	1890

static KEY key211[KEY_PRESTORE]={
    {FORM_84,0,0x0809,0x40040100},		//1
    {FORM_84,0,0x8889,0x40040100},		//2
    {FORM_84,0,0x4849,0x40040100},		//3
    {FORM_84,0,0xc8c9,0x40040100},		//4
    {FORM_84,0,0x2829,0x40040100},		//5
    {FORM_84,0,0xa8a9,0x40040100},		//6
    {FORM_84,0,0x6869,0x40040100},		//7

    {FORM_84,0,0xe8e9,0x40040100},		//8
    {FORM_84,0,0x1819,0x40040100},		//9
    {FORM_84,0,0x9899,0x40040100},		//0
    {FORM_84,0,0xdcdd,0x40040100},		//11: Digi
    {FORM_84,0,0x9c9d,0x40040100},		//12: Disp
    {FORM_84,0,0xa0a1,0x40040100},		//13: Source
    {FORM_84,0,0x4c4d,0x40040100},		//14: Mute
    {FORM_84,0,0xbcbd,0x40040100},		//15: Power

    {FORM_84,0,0xacad,0x40040100},		//16: ChM
    {FORM_84,0,0x2c2d,0x40040100},		//17: ChP
    {FORM_84,0,0x8485,0x40040100},		//18: VolM
    {FORM_84,0,0x0405,0x40040100},		//19: VolP
    {FORM_84,0,0x4a4b,0x40040100},		//20: Menu
    {0},					//21: Enter
    {0},					//22: Exit
    {FORM_84,0,0xcbca,0x40040100},		//23: Info

    {FORM_84,0,0x9293,0x40040100},		//24: Ok
    {FORM_84,0,0xf2f3,0x40040100},		//25: Right
    {FORM_84,0,0xd2d3,0x40040100},		//26: Down
    {FORM_84,0,0x7273,0x40040100},		//27: Left
    {FORM_84,0,0x5253,0x40040100},		//28: Up
    {0},					//29
    {FORM_84,0,0x505d,0x40040d00},		//30: Play
    {FORM_84,0,0x606d,0x40040d00},		//31: Pluse

    {FORM_84,0,0x000d,0x40040d00},		//32: Stop
    {FORM_84,0,0x0000,0x40040100},		//33: Eject
    {FORM_84,0,0x0000,0x40040100},		//34: Rec
    {FORM_84,0,0x525f,0x40040d00},		//35: Ffwd
    {FORM_84,0,0x929f,0x40040d00},		//36: Bkwd
    {FORM_84,0,0x0000,0x40040100},		//37: Prev
    {FORM_84,0,0x0000,0x40040100},		//38: Next
    {FORM_84,0,0x0000,0x40040100},		//39: Subtitle

    {FORM_84,0,0x0000,0x40040100},		//40: Angle
    {FORM_84,0,0x0000,0x40040100},		//41: Zoom
    {FORM_84,0,0x0000,0x40040100}		//42: Lang
};

static KEY key_tcl[KEY_PRESTORE]={
    {FORM_08,0,0,0x0202807f},			//1
    {FORM_08,0,0,0x020240bf},			//2
    {FORM_08,0,0,0x0202c03f},			//3
    {FORM_08,0,0,0x020220df},			//4
    {FORM_08,0,0,0x0202a05f},			//5
    {FORM_08,0,0,0x0202609f},			//6
    {FORM_08,0,0,0x0202e01f},			//7

    {FORM_08,0,0,0x020210ef},			//8
    {FORM_08,0,0,0x0202906f},			//9
    {FORM_08,0,0,0x0202a25d},			//0
    {0},					//11: Digi
    {0},					//12: Disp
    {FORM_08,0,0,0x0202827d},			//13: Source
    {FORM_08,0,0,0x0202f00f},			//14: Mute
    {FORM_08,0,0,0x020250af},			//15: Power

    {FORM_08,0,0,0x02027887},			//16: ChM
    {FORM_08,0,0,0x0202f807},			//17: ChP
    {FORM_08,0,0,0x020238c7},			//18: VolM
    {FORM_08,0,0,0x0202a857},			//19: VolP
    {FORM_08,0,0,0x020202fd},			//20: Menu
    {0},					//21: Enter
    {0},					//22: Exit
    {0},					//23: Info

    {FORM_08,0,0,0x0202b04f},			//24: Ok
    {FORM_08,0,0,0x02028877},			//25: Right
    {FORM_08,0,0,0x0202708f},			//26: Down
    {FORM_08,0,0,0x020208f7},			//27: Left
    {FORM_08,0,0,0x0202d02f},			//28: Up
    {0},					//29
    {0},					//30: Play
    {0},					//31: Pluse

    {0},					//32: Stop
    {0},					//33: Eject
    {0},					//34: Rec
    {0},					//35: Ffwd
    {0},					//36: Bkwd
    {0},					//37: Prev
    {0},					//38: Next
    {0},					//39: Subtitle

    {0},					//40: Angle
    {0},					//41: Zoom
    {0}						//42: Lang
};

static u32	NilCodec	(BEAM*,KEY*);
static u32	Encode00	(BEAM*,KEY*);
static u32	Encode0832	(BEAM*,KEY*);
static u32	Encode44	(BEAM*,KEY*);
static u32	Encode8448	(BEAM*,KEY*);
static u32	Encode88	(BEAM*,KEY*);
static u32	EncodeWH	(BEAM*,KEY*,u32,u32,u32);

static u32(*encode[])(BEAM*,KEY*)={
    Encode00,
    Encode0832,
    Encode44,
    Encode8448,
    Encode88,
    NilCodec,
    NilCodec,
    NilCodec
};

static u32 NilCodec(BEAM *b,KEY *k){
    return 0;
}

static u32 Pack(KEY *key,u16 *src){
    u32	e,i,k,v;
    u32	*d;

    d=&key->data2;
    for(k=64;k;k-=32){
	for(i=32;i;i--){
	    if(e=*src++){
		if((e>>8)&&((e&255)==1)){
		    if(e=*src++){
			if(!(e>>8)){
			    v<<=1;
			    if(e>1)
				v|=1;
			    continue;
			}
		    }
		}
		else return 0;
	    }
	    *d=v<<i;
	    goto L1;
	}
	*d--=v;
    }
L1:
    return 96-k-i;
}

static u8 Unpack(u16 *dst,KEY *key,u8 size,u8 fact,u16 pulse){
    u32	*s;
    s32	a;
    u32	i,r,v;

    r=0;
    s=&key->data2;
    for(a=size;a>0;a-=32){
	v=*s--;
	for(i=a>32?32:a;i;i--){
	    *dst++=pulse;
	    if(v&0x80000000){
		*dst++=0;
		*dst++=0;
		*dst++=0;
		r+=4;
	    }
	    else{
		*dst++=0;
		r+=2;
	    }
	    v<<=1;
	}
    }
    *dst++=pulse;
    *dst++=0;
    *dst++=0;
    *dst++=0;
    return r+3;
}

static u32 DecodeNec(BEAM *beam,KEY *key){
    u16	*p;
    u32	a;

    p=beam->wave;
    if((*p++&255)>14){
	if(*p++==8){
	    a=Pack(key,p);
	    key->vendor=FORM_08;
	    beam->period=1956;
	    beam->pulse=800;
	    beam->repetition=16;
	    beam->head=a;
	    return a;
	}
    }
    return 0;
}

static u32 Encode00(BEAM *beam,KEY *key){
    return EncodeWH(beam,key,0,0,8);
}

static u32 Encode0832(BEAM *beam,KEY *key){
    u32	i,p;
    u16	*d;

    if(key->vendor!=FORM_08)
	return 0;

    p=PERIOD_38/2;
    d=beam->wave;
    for(i=26;i;i--)
	*d++=0;
    d=beam->wave+2;
    for(i=16;i;i--)
	*d++=p;
    beam->period=PERIOD_38;
    beam->pulse=p;
    beam->repetition=19;
    beam->head=Unpack(d+8,key,32,3,p)+26;
    return 1;
}

static u32 Encode44(BEAM *beam,KEY *key){
    return EncodeWH(beam,key,4,4,8);
}

static u32 Encode88(BEAM *beam,KEY *key){
    return EncodeWH(beam,key,8,8,8);
}

static u32 Decode211(BEAM *beam,KEY *key){
    u16	*p,v;
    u32	a;

    p=beam->wave;
    v=*p++;
    if((v&0xff00)&&(v&255)==8){
	if(*p++==4){
	    a=Pack(key,p);
	    key->vendor=FORM_84;
	    beam->period=1956;
	    beam->pulse=800;
	    beam->repetition=16;
	    beam->head=a;
	    return a;
	}
    }
    return 0;
}

static u32 Encode8448(BEAM *beam,KEY *key){
    u16	p;
    u16	*dst;

    if(key->vendor!=FORM_84)
	return 0;

    p=PERIOD_36/2;
    dst=beam->wave;
    *dst++=0;
    *dst++=0;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=p;
    *dst++=0;
    *dst++=0;
    *dst++=0;
    *dst++=0;
    beam->period=PERIOD_36;
    beam->pulse=p;
    beam->repetition=15;
    beam->head=Unpack(dst,key,48,3,p)+14;
    return 1;
}

static u32 EncodeWH(BEAM *beam,KEY *keu,u32 head1,u32 head0,u32 len){
    return 0;
}

u8 Decode(BEAM *beam,KEY *key){
    u32	r;

    r=DecodeNec(beam,key);
    return r?r:Decode211(beam,key);
}

u32 Encode(BEAM *beam,KEY *key){
    return encode[key->vendor](beam,key);
}

void Load(u32 device,KEY *buff,u32 len,u32 extra){
    KEY	*d,*s,*x;

    d=buff+1;
    if(device==DEV_PANA)
	s=key211;
    else s=key_tcl;
    for(x=s+KEY_PRESTORE;s<x;d++,s++)
	*d=*s;
}
